package com.wanghua.spring.action;

import com.opensymphony.xwork2.ActionSupport;
import com.wanghua.spring.bean.entity.Attachment;
import com.wanghua.spring.bean.entity.Mail;
import com.wanghua.spring.dao.IDao;
import com.wanghua.spring.util.FileUtil;
import com.wanghua.spring.util.JavaProperties;
import com.wanghua.spring.util.Pagination1;
import com.wanghua.spring.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

//Spring负责生成Action对象。id属性值对应 struts.xml中<action>的class属性值。因为Struts2的Action不是单个实例，因此scope属性需要配置为 prototype。

@Scope("prototype")
@Controller("mailAction")
public class MailAction extends ActionSupport {
    protected Log log = LogFactory.getLog(getClass());

    public static final String ADD = "add";     //添加邮件操作
    public static final String LIST = "list";   //列出邮件操作

    @Resource
    private IDao dao;    //将由 Spring 注射进来
    @Resource
    private JavaMailSenderImpl mailSender;   //将由 Spring 注射进来

    private Mail mail;    //Mail对象，手机浏览器提交的信息
    private String from; //手机浏览器提交的信息

    /*注意：Struts2 会将文件自动上传到临时文件夹中，并把文件设置到 attachment 文件数组上，原文件名设置到 attachmentFileName 数组上。
      运行完毕后临时文件会被自动删除。因此下面两个属性是自动被填充的，不需要我们来设置他们的值。*/
    private File[] attachment;   //多个附件文件，发送附件时使用
    private String[] attachmentFileName;  //多个附件的名字

    private String title;
    private String message;
    private String action;
    private String sort;
    private String order;

    public MailAction() {
        try {
            //当前web应用的绝对路径：D:\技术区\Java\Spring\Spring\out\artifacts\spring_war_exploded\WEB-INF\classes\jdbc.properties
            //在JavaBean里可以这样: this.getClass().getClassLoader().getResource("/").getPath();
            ServletContext context = ServletActionContext.getRequest().getSession().getServletContext();
            String path = context.getRealPath("/WEB-INF/classes/jdbc.properties");   //src 下的 properties 文件调试时会到 /WEB-INF/classes 目录下。
            this.from = JavaProperties.getValue(path, "mail.smtp.from");
        } catch (IOException e) {
            log.error(e, e);
        }
    }

    @Transactional(rollbackFor = Exception.class) //此标签不能放 add()，因为在同一个类中一个方法调用另一个有事务的方法，事务是不会起作用的。这里checked异常也会被回滚了，默认不会。
    @Override
    public String execute() throws UnsupportedEncodingException {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        HttpSession session = request.getSession(true);

        response.setCharacterEncoding("UTF-8");
        request.setCharacterEncoding("UTF-8");
        if (ADD.equals(action))
            return add();  //发送邮件，发送完列出邮件列表
        return list();  //否则列出邮件列表
    }

    //发送邮件
    public String add() {
        this.setTitle("发送邮件");
        if (mail == null)
            return ADD;  //返回添加页面

        if (StringUtil.isNull(mail.getSubject())) {
            setMessage("请填写邮件主题");
            return ADD;
        }
        mail.setFrom(from);  //设置发件人

        if (!mail.isMimeMessage()) {   //发送简单的文本邮件
            SimpleMailMessage simpleMailMessage = new SimpleMailMessage();  //简单邮件
            try {
                simpleMailMessage.setTo(StringUtil.parseEmail(mail.getTo()));  //设置发件人。(发件人、抄送人、暗送人只要有一个地址就可以发出去)
                simpleMailMessage.setCc(StringUtil.parseEmail(mail.getCc()));  //设置抄送人
                simpleMailMessage.setBcc(StringUtil.parseEmail(mail.getBcc()));  //设置暗送人
                simpleMailMessage.setFrom(mail.getFrom());  //设置发件人
                simpleMailMessage.setSubject(mail.getSubject());  //设置主题
                simpleMailMessage.setText(mail.getContent());  //设置内容
                mailSender.send(simpleMailMessage);  //发送
                mail.setSent(true);  //标记发送成功
            } catch (Throwable e) {
                log.error(e, e);
                setMessage("发送失败：" + e.getMessage());
                mail.setErrorMessage(e.getMessage());
            }
        } else {  //发送HTML内容邮件代码
            MimeMessage m = mailSender.createMimeMessage();
            try {
                MimeMessageHelper helper = new MimeMessageHelper(m, true, "GBK");
                helper.setTo(StringUtil.parseEmail(mail.getTo()));
                helper.setCc(StringUtil.parseEmail(mail.getCc()));
                helper.setBcc(StringUtil.parseEmail(mail.getBcc()));
                helper.setFrom(mail.getFrom());
                helper.setSubject(mail.getSubject());
                helper.setText(mail.getContent(), true);  //设置HTML内容
                attachment = FileUtil.saveFiles(attachment, attachmentFileName);  //保存文件
                for (int i = 0; attachment != null && i < attachment.length; i++) {
                    File file = attachment[i];
                    FileSystemResource source = new FileSystemResource(file);  //附件源
                    helper.addAttachment(attachmentFileName[i], source);  //添加

                    Attachment a = new Attachment();
                    a.setFilename(attachmentFileName[i]);  //设置文件名
                    a.setFilepath(file.getAbsolutePath());   //设置实际路径
                    mail.getAttachments().add(a);   //添加到 mail 对象中
                }
                mailSender.send(m);
                mail.setSent(true);
            } catch (Exception e) {
                log.error(e, e);
                setMessage("发送失败：" + e.getMessage());
                mail.setErrorMessage(e.getMessage());
            }
        }

        dao.create(mail); //将Mail对象记录到数据库
        return list();
    }

    //已发送邮件列表
    public String list() {
        HttpServletRequest request = ServletActionContext.getRequest();
        HttpServletResponse response = ServletActionContext.getResponse();
        HttpSession session = request.getSession(true);

        this.setTitle("邮件列表");
        if (StringUtil.isNull(sort))
            sort = "id";
        if (StringUtil.isNull(order))
            order = "desc";

        String hql = " from Mail m order by m." + sort + " " + order;
        int count = dao.getTotalCount("select count(m) " + hql);

        Pagination1 pagination = new Pagination1(request, response);
        pagination.setRecordCount(count);
        List<Mail> mailList = dao.list(hql, pagination.getFirstResult(), pagination.getPageSize());

        request.setAttribute("mailList", mailList);
        request.setAttribute("pagination", pagination);
        return LIST;
    }

    public IDao getDao() {
        return dao;
    }

    public void setDao(IDao dao) {
        this.dao = dao;
    }

    public JavaMailSenderImpl getMailSender() {
        return mailSender;
    }

    public void setMailSender(JavaMailSenderImpl mailSender) {
        this.mailSender = mailSender;
    }

    public Mail getMail() {
        return mail;
    }

    public void setMail(Mail mail) {
        this.mail = mail;
    }

    public File[] getAttachment() {
        return attachment;
    }

    public void setAttachment(File[] attachment) {
        this.attachment = attachment;
    }

    public String[] getAttachmentFileName() {
        return attachmentFileName;
    }

    public void setAttachmentFileName(String[] attachmentFileName) {
        this.attachmentFileName = attachmentFileName;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }

    public String getSort() {
        return sort;
    }

    public void setSort(String sort) {
        this.sort = sort;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }
}
